package com.wsjc.web.config;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

@Component
public class RedisInitServers {
	
	
	private static Logger logger = Logger.getLogger(RedisInitServers.class);
	
	private static String useWayCode = "";
	// key ip , value 连接池
    private static Map<String, JedisPool> servers = new HashMap<String, JedisPool>();
	
	private static JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
	
	static {
		
//		<!-- 最大连接数 -->
		jedisPoolConfig.setMaxTotal(Integer.valueOf(JedisConfig.readConfig("jedis.config.maxTotal")));
//		<!-- 最大空闲连接数 -->
		jedisPoolConfig.setMaxIdle(Integer.valueOf(JedisConfig.readConfig("jedis.config.maxIdle")));
//		<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
		jedisPoolConfig.setMaxWaitMillis(Integer.valueOf(JedisConfig.readConfig("jedis.config.maxWaitMillis")));
//		<!-- 连接最小空闲时间 -->
		jedisPoolConfig.setMinEvictableIdleTimeMillis(Integer.valueOf(JedisConfig.readConfig("jedis.config.minEvictableIdleTimeMillis")));
//		<!-- 每次释放连接的最大数目 -->
		jedisPoolConfig.setNumTestsPerEvictionRun(Integer.valueOf(JedisConfig.readConfig("jedis.config.numTestsPerEvictionRun")));
//		<!-- 释放连接的扫描间隔（毫秒） -->
		jedisPoolConfig.setTimeBetweenEvictionRunsMillis(Long.valueOf(JedisConfig.readConfig("jedis.config.numTestsPerEvictionRun")));
//		<!-- 连接最小空闲时间 --> -->
		jedisPoolConfig.setMinEvictableIdleTimeMillis(Long.valueOf(JedisConfig.readConfig("jedis.config.timeBetweenEvictionRunsMillis")));
//		<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
		jedisPoolConfig.setSoftMinEvictableIdleTimeMillis(Long.valueOf(JedisConfig.readConfig("jedis.config.softMinEvictableIdleTimeMillis")));
//		<!-- 在获取连接的时候检查有效性, 默认false -->
		jedisPoolConfig.setTestOnReturn(Boolean.valueOf(JedisConfig.readConfig("jedis.config.testOnBorrow")));
//		<!-- 在空闲时检查有效性, 默认false -->
		jedisPoolConfig.setTestWhileIdle(Boolean.valueOf(JedisConfig.readConfig("jedis.config.testWhileIdle")));
//		<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
		jedisPoolConfig.setBlockWhenExhausted(Boolean.valueOf(JedisConfig.readConfig("jedis.config.blockWhenExhausted")));

		// 使用方式代码号
		useWayCode = JedisConfig.readConfig("use.way.code");
		logger.info("REDIS-MONITOR|INFO|init-servers|use.way.code = " + useWayCode);
		if(!StringUtils.isEmpty(useWayCode) && (useWayCode.equals("JavaSentinel") || useWayCode.equals("ServerSentinel"))){
			String masterAddress = JedisConfig.readConfig("redis.sentinel.master.address") ; 
			initSentinelServers(masterAddress);
		}else if(useWayCode.equals("Agent")){
			String jedisAddress = JedisConfig.readConfig("jedis.agent.address") ; 
			initServers(jedisAddress);
		}else if(useWayCode.equals("Cluster")){
			String jedisAddress = JedisConfig.readConfig("jedis.cluster.nodes") ;
			initSentinelServers(jedisAddress);
		}
		
	}
	
	/**
	 * 代理 和 cluster 初始化方法
	 * @param address
	 */
	public static void initServers(String address) {
		
		try {
			//"127.0.0.1:6379;127.0.0.1:6380;127.0.0.1:6381" ;
			String[] urls = address.split(";") ;
			for(String url : urls){
		        String[] serverInfo = url.split(":");
		        String host = serverInfo[0] ;
		        int port = Integer.parseInt(serverInfo[1]) ;
		        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, 100000, JedisConfig.readConfig("redis.auth.password"));
				servers.put(host+":"+port, jedisPool) ;
			}
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("REDIS-MONITOR|ERROR|init-servers|initServers 初始化失败, useWayCode = " + useWayCode + "...e:", e);
		}
		
		
		
	}
	
	
	/**
	 * 哨兵初始化方法
	 */
	private static void initSentinelServers(String masterAddress) {
		
		// 获取所有slave
		try {
			String masterHost = masterAddress.split(":")[0];
			int masterPort = Integer.parseInt(masterAddress.split(":")[1]);
			Jedis jedis = new Jedis(masterHost, masterPort);
			String info_replication = jedis.info("replication");
			// 解析info replication
			String[] lines = info_replication.split("\r\n");
			int slaveCount = Integer.parseInt(lines[2].split(":")[1]);
			if (slaveCount > 0) {
				for (int i = 0; i < slaveCount; i++) {
					String host = lines[3 + i].split(",")[0].split("=")[1];
					int port = Integer.valueOf(lines[3 + i].split(",")[1].split("=")[1]);
					JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, 100000, JedisConfig.readConfig("redis.auth.password"));
					servers.put(host+":"+port, jedisPool) ;
				}
			}
			jedis.close();
		} catch (Exception e) {
			e.printStackTrace();
			logger.error("REDIS-MONITOR|ERROR|init-servers|initSentinelServers 哨兵 servers 初始化失败...e:", e);
		}
	}
	
	
	
	public JedisPool getJedisPoll(String address){
		
		JedisPool jedisPool = servers.get(address);
		if(null == jedisPool){
			String host = address.split(":")[0];
			int port = Integer.parseInt(address.split(":")[1]);
			jedisPool = new JedisPool(jedisPoolConfig, host, port, 100000, JedisConfig.readConfig("redis.auth.password"));
			servers.put(host+":"+port, jedisPool) ;
		}
		
		return jedisPool;
	}
	
	/** 获取redis nodes address **/
    public List<String> getNodesInfo(){
		
    	List<String> address = new ArrayList<String>();
		for(Entry<String, JedisPool> pair: servers.entrySet()){
			address.add(pair.getKey());
		}
		return address;
	}
	
	
    public String getJedisStatus(String address){
    	
		JedisPool jedisPool = servers.get(address);
		Jedis jedis = jedisPool.getResource();
		String pong = jedis.ping();
		if(!StringUtils.isEmpty(pong) && pong.equals(pong)){
			return "run";
		}
		return "noRun";
	}
    
    
    
    
    
    
    
    
    
    
    

}
